package tp.pr4;

import tp.pr4.gui.NavigationPanel;
import tp.pr4.instructions.exceptions.InstructionExecutionException;
import tp.pr4.items.Item;

/**
 * This class is in charge of the robot navigation features. It contains the city where the 
 * robot looks for garbage, the current place where the robot is, and the current direction 
 * of the robot. It contains methods to handle the different robot movements and to pick and 
 * drop items at the current place.
 * @author Alvaro Saez Hernando
 * @author Noel Clemente Montero 
 */
public class NavigationModule {
	
	private City aCity;
	private Place initialPlace;
	private Direction direction;

	/**
	 * Navigation module constructor. It needs the city map and the initial place
	 * @param aCity A city map
	 * @param initialPlace An initial place for the robot
	 */
	public NavigationModule(City aCity,Place initialPlace){
		this.aCity = aCity;
		this.initialPlace = initialPlace;
		this.direction = Direction.NORTH;
	}
	
	/**
	 * Checks if the robot has arrived at a spaceship
	 * @return true if an only if the current place is the spaceship
	 */
	public boolean atSpaceship(){
		return initialPlace.isSpaceship();
	}
	
	/**
	 * Updates the current direction of the robot according to the rotation
	 * @param rotation left or right
	 */
	public void rotate(Rotation rotation){
		if(rotation.equals(Rotation.LEFT))
			turnleft();
		
		else if(rotation.equals(Rotation.RIGHT))
			turnright();
		
	}
	
	/**
	 * The method tries to move the robot following the current direction. If the movement is not
	 * possible because there is no street, or there is a street which is closed, then it throws 
	 * an exception. Otherwise the current place is updated according to the movement
	 * @throws InstructionExecutionException An exception with a message about the encountered problem
	 */
	public void move()throws InstructionExecutionException{
		Street street = this.aCity.lookForStreet(this.initialPlace,this.direction);
			if(street!=null){
					if(street.isOpen()){
						this.initialPlace = street.nextPlace(initialPlace);
					}
					else throw new InstructionExecutionException ("la calle esta cerrada");
			}
			else throw new InstructionExecutionException ("no existe calle");
			
	}
	
	/**
	 * Tries to pick an item characterized by a given identifier from the current place. If the action 
	 * was completed the item is removed from the current place.
	 * @param id The identifier of the item
	 * @return The item of identifier id if it exists in the place. Otherwise the method returns null
	 */
	public Item pickItemFromCurrentPlace(String id){
		if (this.initialPlace.existItem(id)){
			return initialPlace.pickItem(id);
		}
		else return null;
		}
	
	/**
	 * Drop an item in the current place. It assumes that there is no other item with the same name/id 
	 * there. Otherwise, the behaviour is undefined.
	 * @param it The name of the item to be dropped.
	 */
	public void dropItemAtCurrentPlace(Item it){
		if (findItemAtCurrentPlace(it.getId())){
			System.out.println("este item ya existe en este lugar");//Comentario que se tendra que eliminar.
		}
		else this.initialPlace.addItem(it);
		
	}
	
	/**
	 * Checks if there is an item with a given id in this place
	 * @param id Identifier of the item we are looking for
	 * @return true if and only if an item with this id is in the current place
	 */
	public boolean findItemAtCurrentPlace(String id){
		if (this.initialPlace.existItem(id)){
			return true;
		}
		else return false;
		
	}
	
	/**
	 * Initializes the current heading according to the parameter
	 * @param heading New direction for the robot
	 */
	public void initHeading(Direction heading){
		this.direction = heading;
	}
	
	/**
	 * Prints the information (description + inventory) of the current place
	 */
	public void scanCurrentPlace(){
		System.out.println(this.initialPlace.toString());
	}
	
	/**
	 * Returns the street opposite the robot
	 * @return The street which the robot is facing, or null, if there is not any street in this direction
	 */
	public Street getHeadingStreet(){
		
		return this.aCity.lookForStreet(this.initialPlace, this.direction);
		
	}
	
	/**
	 * Returns the robot heading
	 * @return The direction where the robot is facing to.
	 */
	public Direction getCurrentHeading(){
		
		return this.direction;
		
	}
	
	/**
	 * Returns the current place where the robot is (for testing purposes)
	 * @return The current place
	 */
	public Place getCurrentPlace(){
		
		return this.initialPlace;
		
	}
	/**
	 * Sets a panel in order to show its information in a GUI
	 * @param navPanel The panel where the navigation module will show its information
	 */
	public void setNavigationPanel(NavigationPanel navPanel){
		
	}

	/**
	 * Turn left to wall·e
	 */
	private void turnleft(){
		if(this.direction==Direction.NORTH){
			this.direction = Direction.WEST;
		}
		else if(this.direction==Direction.WEST){
			this.direction = Direction.SOUTH;					
		}
		else if(this.direction==Direction.SOUTH){
			this.direction = Direction.EAST;			
		}
		else if(this.direction==Direction.EAST){
			this.direction = Direction.NORTH;
		}
		
	}
	
	/**
	 * Turn right to wall·e
	 */
	private void turnright(){
		if(this.direction==Direction.NORTH){
			this.direction = Direction.EAST;
		}
		else if(this.direction==Direction.WEST){
			this.direction = Direction.NORTH;					
		}
		else if(this.direction==Direction.SOUTH){
			this.direction = Direction.WEST;			
		}
		else if(this.direction==Direction.EAST){
			this.direction = Direction.SOUTH;
		}
		
	}

}
